package net.myspring.middle.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import net.myspring.common.mybatis.domain.Page;
import net.myspring.common.mybatis.domain.Pageable;
import net.myspring.common.utils.Collections3;
import net.myspring.common.utils.StringUtils;
import net.myspring.common.utils.ThreadLocalContext;
import net.myspring.middle.domain.Account;
import net.myspring.middle.domain.Department;
import net.myspring.middle.domain.Menu;
import net.myspring.middle.mapper.AccountMapper;
import net.myspring.middle.mapper.DepartmentMapper;
import net.myspring.middle.mapper.RoleMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Base64Utils;

import java.util.List;
import java.util.Map;

/**
 * Created by liuj on 16/7/10.
 */
@Service
public class AccountService {
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private DepartmentMapper departmentMapper;

    public Account findOne(String id) {
        Account account = accountMapper.findOne(id);
        account.setRoleSet(Sets.newLinkedHashSet(roleMapper.findByAccountId(id)));
        return account;
    }

    public Page<Account> findPage(Pageable pageable, Map<String, Object> map) {
        Page<Account> page = accountMapper.findPage(pageable, map);
        return page;
    }

    private List<Department> list = Lists.newArrayList();
    public List<Account> findReport(){
        List<Account> accountList;
        Account account = ThreadLocalContext.get().getAccount();
        getChildList(departmentMapper.findOne(account.getDepartmentId()));
        if(list.size()==0){
            accountList = accountMapper.findByDepartmentIds(Lists.newArrayList(account.getDepartmentId()));
        }else{
            List<String> departmentIds = Collections3.extractToList(list,"id");
            accountList = accountMapper.findByDepartmentIds(departmentIds);
        }
        return  accountList;
    }
    private void getChildList(Department department){
        List<Department> childList = departmentMapper.findByParentId(department.getId());
        for(Department child : childList){
            getChildList(child);
            list.add(child);
        }
    }

    @Transactional
    public Account save(Account account) {
        if (StringUtils.isNotBlank(account.getPassword())) {
            account.setPassword(passwordEncoder.encode(account.getPassword()));
        }
        if (account.isCreate()) {
            accountMapper.save(account);
        } else {
            accountMapper.update(account);
            accountMapper.deleteRoleByAccountId(account.getId());
        }
        if (Collections3.isNotEmpty(account.getRoleIds())) {
            accountMapper.saveRoles(account.getId(), account.getRoleIds());
        }
        return account;
    }

    @Transactional
    public Account cloudSave(Account account) {
        if (StringUtils.isNotBlank(account.getPassword())) {
            account.setPassword(passwordEncoder.encode(account.getPassword()));
        }
        if (StringUtils.isNotBlank(account.getOutPassword())) {
            account.setOutPassword(Base64Utils.encodeToString(account.getOutPassword().getBytes()));
        }
        accountMapper.update(account);
        return account;
    }

    public boolean checkLoginName(Account account) {
        Account checkAccount = accountMapper.findByLoginName(account.getLoginName());
        return checkAccount == null || (checkAccount.getId().equals(account.getId()));
    }

    @Transactional
    public void delete(Account account) {
        account.setEnabled(false);
        accountMapper.update(account);
    }

    public Boolean removeTab(String menuId) {
        String cacheName = "historyMenus_" + ThreadLocalContext.get().getAccount().getId();
        List<Menu> menus = (List<Menu>) redisTemplate.opsForValue().get(cacheName);
        List<Menu> menuList = Lists.newArrayList();
        for (Menu menu : menus) {
            if (!menu.getId().equals(menuId)) {
                menuList.add(menu);
            }
        }
        redisTemplate.opsForValue().set(cacheName, menuList);
        return true;
    }

    public Boolean removeAllTab() {
        String cacheName = "historyMenus_" + ThreadLocalContext.get().getAccount().getId();
        redisTemplate.opsForValue().set(cacheName, null);
        return true;
    }
}
